﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;
using System.Xml;
using Easyleave.Logic.Domain;

namespace Easyleave.Logic.Membership
{
    /// <summary>
    /// Access information of the recommendation hierachy required for leave approval. 
    /// This information will generally come from an external system.
    /// </summary>
    public class MembershipImpl: IMembership
    {
        private XmlDocument doc = new XmlDocument();
        public MembershipImpl()
        {
            Assembly assembly = typeof(MembershipImpl).Assembly;
            string ns = assembly.GetName().Name.ToString() + ".Membership";
            Stream xmlStream = assembly.GetManifestResourceStream(ns + ".Membership.xml");
            doc.Load(xmlStream);
        }

        public UserDto Authenticate(string username, string password)
        {
            string xpath1 = string.Format("/users/user[auth/@username='{0}' and auth/@password='{1}']", new string[] { username, password });
            XmlNode userNode = doc.SelectSingleNode(xpath1);
            if (userNode != null)
            {
                Guid id = new Guid(((XmlElement)userNode).GetAttribute("id"));
                XmlElement authEle = (XmlElement)((XmlElement)userNode).GetElementsByTagName("auth")[0];
                string fullname = authEle.GetAttribute("fullname");

                string[] roles = authEle.GetAttribute("roles").Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                return new UserDto() { Username = username, Fullname = fullname, Roles = roles, Id = id };
            }
            return null;
        }

        public UserDto GetUser(Guid? userId)
        {
            string xpath1 = string.Format("/users/user[@id='{0}']", new string[] { userId.ToString().ToUpper() });
            XmlNode userNode = doc.SelectSingleNode(xpath1);
            if (userNode != null)
            {

                XmlElement authEle = (XmlElement)((XmlElement)userNode).GetElementsByTagName("auth")[0];
                string fullname = authEle.GetAttribute("fullname");
                string username = authEle.GetAttribute("username");

                string[] roles = authEle.GetAttribute("roles").Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                return new UserDto() { Username = username, Fullname = fullname, Roles = roles, Id = userId };
            }
            return null;
        }

        /// <summary>
        /// Get the next person in the recommendation hierachy for this user
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="currentRecommenderId"></param>
        /// <returns></returns>
        public Guid GetNextRecommender(Guid? userId, Guid? currentRecommenderId)
        {
            // get next recommender order
            int nextRecommenderOrder = 1;
            if (Guid.Empty != currentRecommenderId)
            {
                string xpath1 = string.Format("/users/user[@id='{0}']/managers/recommender[@id='{1}']/@order", new string[] { userId.ToString().ToUpper(), currentRecommenderId.ToString().ToUpper() });
                XmlNode currentOrderAtt = doc.SelectSingleNode(xpath1);
                if (currentOrderAtt == null) return Guid.Empty;
                nextRecommenderOrder = int.Parse(((XmlAttribute)currentOrderAtt).Value) + 1;
            }

            //get next recommender id
            string xpath2 = string.Format("/users/user[@id='{0}']/managers/recommender[@order='{1}']/@id", new string[] { userId.ToString().ToUpper(), nextRecommenderOrder.ToString() });
            XmlNode nextRecommender = doc.SelectSingleNode(xpath2);
            if (nextRecommender == null) return Guid.Empty;
            return new Guid(((XmlAttribute)nextRecommender).Value);
        }

        /// <summary>
        /// Get the person who will approve/reject the leave
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public Guid GetApprover(Guid? userId)
        {
            string xpath2 = string.Format("/users/user[@id='{0}']/managers/approver/@id", new string[] { userId.ToString().ToUpper()});
            XmlNode approver = doc.SelectSingleNode(xpath2);
            if (approver == null) return Guid.Empty;
            return new Guid(((XmlAttribute)approver).Value);
        }
    }
}
